package com.atguigu.classroom.vod.service.impl;

import com.atguigu.classroom.model.vod.*;
import com.atguigu.classroom.vo.vod.*;
import com.atguigu.classroom.vod.mapper.*;
import com.atguigu.classroom.vod.service.ChapterService;
import com.atguigu.classroom.vod.service.CourseService;
import com.atguigu.classroom.vod.utils.QiniuUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 课程 服务实现类
 * </p>
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements CourseService {
    @Autowired
    private CourseMapper courseMapper;
    @Autowired
    private TeacherMapper teacherMapper;
    @Autowired
    private SubjectMapper subjectMapper;
    @Autowired
    private CourseDescriptionMapper courseDescriptionMapper;
    @Autowired
    private ChapterMapper chapterMapper;
    @Autowired
    private VideoMapper videoMapper;
    @Autowired
    private ChapterService chapterService;
    @Override
    public Page<Course> getCoursePage(int page, int limit, CourseQueryVo courseQueryVo) {
        LambdaQueryWrapper<Course> courseQueryWrapper=new LambdaQueryWrapper<>();
        courseQueryWrapper.eq(courseQueryVo.getTeacherId()!=null,Course::getTeacherId,courseQueryVo.getTeacherId())
                .eq(courseQueryVo.getSubjectId()!=null,Course::getSubjectId,courseQueryVo.getSubjectId())
                .eq(courseQueryVo.getSubjectParentId()!=null,Course::getSubjectParentId,courseQueryVo.getSubjectParentId())
                .like(courseQueryVo.getTitle()!=null,Course::getTitle,courseQueryVo.getTitle());
        Page<Course> coursePage=new Page<>(page,limit);
        courseMapper.selectPage(coursePage,courseQueryWrapper);//sql-1:查询课程基本信息
        if(coursePage.getRecords().size()==0){//如果根本查不到课程数据，就不需要下面的查询分类名之类的查询了
            return  coursePage;
        }
        List<Long> subjectIdList=new ArrayList<>(coursePage.getRecords().size());
        //存储课程分类id，以下以此类推
        List<Long> subjectParentIdList=new ArrayList<>(coursePage.getRecords().size());
        List<Long> teacherIdList=new ArrayList<>(coursePage.getRecords().size());
        Map<Long,String> subjectNames=new HashMap<>(coursePage.getRecords().size());
        //key是课程分类id,value是课程分类名，以下以此类推
        Map<Long,String> subjectParentNames=new HashMap<>(coursePage.getRecords().size());
        Map<Long,String> teacherNames=new HashMap<>(coursePage.getRecords().size());
        for(Course course:coursePage.getRecords()){
            subjectIdList.add(course.getSubjectId());
            subjectNames.put(course.getSubjectId(),"");
            //课程分类名与父课程分类准备一起查询，因此这里事先将其id进行标识，
            //之后便于判断查出的结果是‘课程分类名’还是‘父课程分类名’
            subjectParentIdList.add(course.getSubjectParentId());
            subjectParentNames.put(course.getSubjectParentId(),"");
            teacherIdList.add(course.getTeacherId());
        }
        LambdaQueryWrapper<Subject> subjectQueryWrapper=new LambdaQueryWrapper<>();
        subjectQueryWrapper.in(Subject::getId,subjectIdList).or()
                           .in(Subject::getId,subjectParentIdList);
        List<Subject> subjectList = subjectMapper.selectList(subjectQueryWrapper);//sql-2:查询课程分类名和父课程分类名
        List<Teacher> teacherList = teacherMapper.selectBatchIds(teacherIdList);//sql-3:查询讲师名
        for (Subject subject:subjectList){
            if(subjectNames.containsKey(subject.getId())){
                //课程分类名中有此课程分类id,说明此对象是通过”in(Subject::getId,subjectIdList)“查询到的
                subjectNames.put(subject.getId(),subject.getTitle());
            }
            if(subjectParentNames.containsKey(subject.getId())){
                //课程分类名中有此父课程分类id,说明此对象是通过”in(Subject::getId,subjectParentIdList)“查询到的
                subjectParentNames.put(subject.getId(),subject.getTitle());
            }
        }
        for(Teacher teacher:teacherList){
            teacherNames.put(teacher.getId(),teacher.getName());
        }
        //此时map集合中已经有数据了（key是***分类id,value是***名）,下面赋值属性params
        coursePage.setRecords(
          coursePage.getRecords().stream().map(course -> {
              Course newCourse=new Course();
              BeanUtils.copyProperties(course,newCourse);
              newCourse.getParam().put("teacherName",teacherNames.get(course.getTeacherId()));
              newCourse.getParam().put("subjectParentTitle",subjectParentNames.get(course.getSubjectParentId()));
              newCourse.getParam().put("subjectTitle",subjectNames.get(course.getSubjectId()));
              return newCourse;
          }).collect(Collectors.toList())
        );
        return coursePage;
    }

    @Override
    @Transactional
    public Long saveCourseInfo(CourseFormVo courseFormVo) {
        Course course=new Course();
        BeanUtils.copyProperties(courseFormVo,course);
        courseMapper.insert(course);
        CourseDescription courseDescription=new CourseDescription();
        courseDescription.setDescription(courseFormVo.getDescription());
        courseDescription.setCourseId(course.getId());
        courseDescriptionMapper.insert(courseDescription);
        return course.getId();
    }

    @Override
    public CourseFormVo getCourseInfoById(Long id) {
        Course course = courseMapper.selectById(id);
        if (course==null){
            return null;
        }
        LambdaQueryWrapper<CourseDescription> courseDescriptionQueryWrapper=new LambdaQueryWrapper<>();
        courseDescriptionQueryWrapper.eq(CourseDescription::getCourseId,id);
        CourseDescription courseDescription = courseDescriptionMapper.selectOne(courseDescriptionQueryWrapper);
        CourseFormVo courseFormVo=new CourseFormVo();
        BeanUtils.copyProperties(course,courseFormVo);
        courseFormVo.setDescription(courseDescription.getDescription());
        return courseFormVo;
    }

    @Override
    @Transactional
    public Long updateCourseFormVo(CourseFormVo courseFormVo) {
        Course course=new Course();
        BeanUtils.copyProperties(courseFormVo,course);
        courseMapper.updateById(course);
        CourseDescription courseDescription=new CourseDescription();
        courseDescription.setCourseId(course.getId());
        courseDescription.setDescription(courseFormVo.getDescription());
        LambdaUpdateWrapper<CourseDescription> courseDescriptionUpdateWrapper=new LambdaUpdateWrapper<>();
        courseDescriptionUpdateWrapper.eq(CourseDescription::getCourseId,course.getId());
        courseDescriptionMapper.update(courseDescription,courseDescriptionUpdateWrapper);
        return course.getId();
    }

    @Override
    public CoursePublishVo getCoursePublishVo(Long id) {
        CoursePublishVo coursePublishVo=new CoursePublishVo();
        //sql-1:查询课程基本信息
        Course course = courseMapper.selectById(id);
        BeanUtils.copyProperties(course,coursePublishVo);
        //sql-2:查询讲师名称
        Teacher teacher = teacherMapper.selectById(course.getTeacherId());
        coursePublishVo.setTeacherName(teacher.getName());
        coursePublishVo.setPrice(String.valueOf(course.getPrice()));
        //sql-2:查询一级分类名和二级分类名
        LambdaQueryWrapper<Subject> subjectQueryWrapper=new LambdaQueryWrapper<>();
        subjectQueryWrapper.in(Subject::getId,course.getSubjectId(),course.getSubjectParentId());
        List<Subject> subjectList = subjectMapper.selectList(subjectQueryWrapper);
        if(subjectList.size()==1){//课程名暂未定 没有父类别
            coursePublishVo.setSubjectParentTitle(subjectList.get(0).getTitle());
        }else if(subjectList.size()==2){
            if (subjectList.get(0).getParentId()==subjectList.get(1).getId()){
                coursePublishVo.setSubjectTitle(subjectList.get(0).getTitle());
                coursePublishVo.setSubjectParentTitle(subjectList.get(1).getTitle());
            }else if (subjectList.get(1).getParentId()==subjectList.get(0).getId()){
                coursePublishVo.setSubjectTitle(subjectList.get(1).getTitle());
                coursePublishVo.setSubjectParentTitle(subjectList.get(0).getTitle());
            }
        }
        return coursePublishVo;
    }

    @Override
    public void publishCourse(long id) {
        Course course=new Course();
        course.setId(id);
        course.setStatus(1);
        course.setPublishTime(new Date());
        courseMapper.updateById(course);
    }

    @Override
    @Transactional
    public void removeCourse(Long id) {
        Course course = courseMapper.selectById(id);
        //sql-1:先查询课程基本信息，用于后面从对象存储删除课程图标
        courseMapper.deleteById(id);//sql-2:删除课程基本信息
        LambdaQueryWrapper<Chapter> chapterQueryWrapper=new LambdaQueryWrapper<>();
        chapterQueryWrapper.eq(Chapter::getCourseId,id);
        chapterMapper.delete(chapterQueryWrapper);//sql-3:删除课程大纲信息
        LambdaQueryWrapper<CourseDescription> courseDescriptionQueryWrapper=new LambdaQueryWrapper<>();
        courseDescriptionQueryWrapper.eq(CourseDescription::getCourseId,id);
        courseDescriptionMapper.delete(courseDescriptionQueryWrapper);//sql-4:删除课程描述信息
        LambdaQueryWrapper<Video> videoQueryWrapper=new LambdaQueryWrapper<>();
        videoQueryWrapper.eq(Video::getCourseId,id);
        List<Video> videos = videoMapper.selectList(videoQueryWrapper);
        //sql-5:先查询课时信息，用于后面从对象存储删除课时视频
        videoMapper.delete(videoQueryWrapper);//sql-6:删除课程的课时信息
        //最后删除对象存储里面的文件；
        List<String> fileKeys=new ArrayList<>(1+videos.size());
        fileKeys.add(course.getCover());
        videos.stream().map(video -> {
            if(video.getVideoSourceId()!=null){
                fileKeys.add(video.getVideoSourceId());
            }
            return null;
        }).collect(Collectors.toList());
        QiniuUtils.deleteFileList(fileKeys);
    }

    @Override
    public List<Course> getCourseListByKeyword(String keyword) {
        LambdaQueryWrapper<Course> courseQueryWrapper=new LambdaQueryWrapper<>();
        courseQueryWrapper.like(Course::getTitle,keyword);
        return courseMapper.selectList(courseQueryWrapper);
    }

    @Override
    public Page findPageCourseWithSPIdAPI(Long subjectParentId, int page, int limit) {
        Page<Course> coursePage=new Page<>(page,limit);
        LambdaQueryWrapper<Course> courseQueryWrapper=new LambdaQueryWrapper<>();
        courseQueryWrapper.eq(Course::getSubjectParentId,subjectParentId);
        courseMapper.selectPage(coursePage,courseQueryWrapper);//sql-1:查询基本数据；
        if(coursePage.getRecords().size()==0){
            return coursePage;
        }
        List<Long> subjectIds=new ArrayList<>(coursePage.getRecords().size()+1);
        List<Long> teacherIds=new ArrayList<>(coursePage.getRecords().size());
        subjectIds.add(subjectParentId);//因为这里就是根据subjectParentId查的，所以直接添进去
        for (Course course:coursePage.getRecords()) {
            subjectIds.add(course.getSubjectId());
            teacherIds.add(course.getTeacherId());
        }
        List<Teacher> teacherList = teacherMapper.selectBatchIds(teacherIds);//sql-2:查询讲师名
        List<Subject> subjectList = subjectMapper.selectBatchIds(subjectIds);//sql-3:查询分类名
        Map<Long,String> teacherNameMap=new HashMap<>(coursePage.getRecords().size());
        Map<Long,String> subjectOrParentNameMap=new HashMap<>(coursePage.getRecords().size()+1);
        //同样，key=id，value=name名字
        for(Teacher teacher:teacherList){
            teacherNameMap.put(teacher.getId(),teacher.getName());
        }
        for(Subject subject:subjectList){
            subjectOrParentNameMap.put(subject.getId(),subject.getTitle());
        }
        List<CourseVo> courseVoList=coursePage.getRecords().stream().map(course -> {
            CourseVo courseVo=new CourseVo();
            BeanUtils.copyProperties(course,courseVo);
            courseVo.setPrice(String.valueOf(course.getPrice()));
            courseVo.setTeacherName(teacherNameMap.get(course.getTeacherId()));
            courseVo.setSubjectTitle(subjectOrParentNameMap.get(course.getSubjectId()));
            courseVo.setSubjectParentTitle(subjectOrParentNameMap.get(course.getSubjectParentId()));
            return courseVo;
        }).collect(Collectors.toList());
        Page<CourseVo> courseVoPage=new Page<>(page,limit);
        BeanUtils.copyProperties(coursePage,courseVoPage);
        courseVoPage.setRecords(courseVoList);
        return courseVoPage;
    }

    @Override
    public Map<String, Object> getCourseInfoAPI(Long courseId) {
        Course course=courseMapper.selectById(courseId);//sql-1:查询课程基本信息
        course.setViewCount(course.getViewCount()+1);
        courseMapper.updateById(course);//sql-2:浏览量+1
        Teacher teacher = teacherMapper.selectById(course.getTeacherId());//sql-3:查询讲师信息
        LambdaQueryWrapper<CourseDescription> descriptionQueryWrapper=new LambdaQueryWrapper<>();
        descriptionQueryWrapper.eq(CourseDescription::getCourseId,courseId);
        CourseDescription courseDescription = courseDescriptionMapper.selectOne(descriptionQueryWrapper);
        //sql-4:查询课程描述信息
        List<ChapterVo> chapterVoList = chapterService.getTreeList(courseId);
        //sql-5,sql-6:调用ChapterService中的方法查询章节Chapter和章节下的小结video
        CourseVo courseVo=new CourseVo();
        BeanUtils.copyProperties(course,courseVo);
        courseVo.setTeacherName(teacher.getName());//查漏补缺-设定讲师名
        courseVo.setPrice(String.valueOf(course.getPrice()));//类型不同这里需要重新设定
        LambdaQueryWrapper<Subject> subjectQueryWrapper=new LambdaQueryWrapper<>();
        subjectQueryWrapper.in(Subject::getId,course.getSubjectId(),course.getSubjectParentId());
        List<Subject> subjectList = subjectMapper.selectList(subjectQueryWrapper);
        //查漏补缺-设定类别名和父类别名👇
        if(subjectList.size()==1){//课程名暂未定 没有父类别
            courseVo.setSubjectParentTitle(subjectList.get(0).getTitle());
        }else if(subjectList.size()==2){
            if (subjectList.get(0).getParentId()==subjectList.get(1).getId()){
                courseVo.setSubjectTitle(subjectList.get(0).getTitle());
                courseVo.setSubjectParentTitle(subjectList.get(1).getTitle());
            }else if (subjectList.get(1).getParentId()==subjectList.get(0).getId()){
                courseVo.setSubjectTitle(subjectList.get(1).getTitle());
                courseVo.setSubjectParentTitle(subjectList.get(0).getTitle());
            }
        }
        Map<String, Object> map = new HashMap<>();
        map.put("courseVo", courseVo);
        map.put("chapterVoList", chapterVoList);
        map.put("description", null!=courseDescription?courseDescription.getDescription():"");
        map.put("teacher", teacher);
        map.put("isBuy", false);//是否购买
        return map;
    }

    @Override
    public List<Course> findlist() {
        List<Course> courses = courseMapper.selectList(null);//sql-1:查询所有课程
        List<Long> teacherIds=new ArrayList<>(courses.size());
        List<Long> subIds=new ArrayList<>(2*courses.size());
        courses.stream().map(course -> {
            teacherIds.add(course.getTeacherId());
            subIds.add(course.getSubjectId());
            subIds.add(course.getSubjectParentId());
            return null;
        }).collect(Collectors.toList());
        List<Teacher> teachers = teacherMapper.selectBatchIds(teacherIds);
        //sql-2:查询所有课程的所有讲师
        List<Subject> subjects = subjectMapper.selectBatchIds(subIds);
        //sql-3:查询所有课程的所有类别名以及父类名
        Map<Long,String> teacherNameMap=new HashMap<>(teachers.size());
        Map<Long,String> subjectOrParentTitleMap=new HashMap<>(subjects.size());
        teachers.stream().map(teacher -> {
            teacherNameMap.put(teacher.getId(),teacher.getName());
            return null;
        }).collect(Collectors.toList());
        subjects.stream().map(subject -> {
            subjectOrParentTitleMap.put(subject.getId(),subject.getTitle());
            return null;
        }).collect(Collectors.toList());

        return courses.stream().map(course -> {
                Course newCourse=new Course();
                BeanUtils.copyProperties(course,newCourse);
                newCourse.getParam().put("teacherName",teacherNameMap.get(newCourse.getTeacherId()));
                if(subjectOrParentTitleMap.containsKey(newCourse.getSubjectId())){
                    newCourse.getParam().put("subjectTitle",subjectOrParentTitleMap.get(newCourse.getSubjectId()));
                }
                if(subjectOrParentTitleMap.containsKey(newCourse.getSubjectParentId())){
                    newCourse.getParam().put("subjectParentTitle",subjectOrParentTitleMap.get(newCourse.getSubjectParentId()));
                }
                return newCourse;
            }).collect(Collectors.toList());
    }
}
